/*
 * File:   Pyramid.h
 * Author: karthik
 *
 * Created on November 14, 2011, 10:06 AM
 */



#ifndef _PYRAMID_H
#define	_PYRAMID_H
#include <math.h>
#include <vector>
#include "ApproximateMedian.h"
#include <iostream>
using std::cerr;
using std::endl;

#include <fstream>
using std::ofstream;

class Pyramid{
    //number of dimensions
    int D;
    int totalrecords;
    double **data;
    int* pointID;
    double indexTime;
    double treeTime;
	ofstream outFile;
	ifstream inFile;


    ApproximateMedian am;

public:
    
    //A structure to hold pyramid number (the actual pyramid number and not the main dimension of pyramid) and height
    struct pyrval{
        int pyramid;
        double height;

        //Constructor
    pyrval(int p, double h)
    {
        pyramid = p;
        height = h;
    }
    //Constructor
    pyrval(){

    }
    };

    pyrval * pv;


   //A function to set number of dimensions
    void setDimension(int d);

    void setdata(double ** d,int tr, int dimension);

    void buildindex();

    void buildSequentialScanData();

    void buildindexHM();

    void buildindexAM();

    void buildindexM();

    void buildtree();

    void savetree();

    void printTree();

    void savemedian();

    void saveblankmedian();

    void loadmedian();

    void loadtree();

    void searchquerypoints(double **d, int tr);

    void searchqueryranges(double *min, double *max, int tr);

    void searchqueryKnn(double **d, int tr, int k);

    void searchLeft(pyrval pv, vector<int>& A, double q[], int k, double* dMax);

    void searchRight(pyrval pv, vector<int>& A, double q[], int k, double* dMax);

    bool in(vector<int> x, int y);

    void searchquerypointsSS(double **d, int tr);

    void searchqueryrangesSS(double *min, double *max, int tr);

    void searchqueryKnnSS(double **d, int tr, int k);

    void searchquerypointsUAppM(double **d, int tr);

    void searchqueryrangesUAppM(double *min, double *max, int tr);

    void searchqueryKnnUAppM(double **d, int tr, int k);

    void searchquerypointsUM(double **d, int tr);

    void searchqueryrangesUM(double *min, double *max, int tr);

    void searchqueryKnnUM(double **d, int tr, int k);

    void selection_sort(vector<int>& A, double point[]);

    void openOutFile(char * fileName);

    void closeOutFile();

    void openInFile(char * fileName);

    void closeInFile();



//Query range stored with pyramid main dimension and height low, and height high values
    struct queryrange{
        int pyramid;
        double h_low;
        double h_high;
    };

    //A function to calculated pyramid value
    Pyramid::pyrval pyramidvalue(std::vector<double> values);

    Pyramid::pyrval pyramidvalue(double values[]);
    //A function to calculated pyramid value
    //using approximate median
    Pyramid::pyrval pyramidvalue_am(double values[]);

    Pyramid::pyrval pyramidvalue_m(double values[]);

    //A function to calculate the pyramid number (the actual pyramid number and not the main dimension of the pyramid) and height low and height high for range search,
    //using the approximate median
    Pyramid::queryrange* getqueryrange_am(double qval[][2]);

    Pyramid::queryrange* getqueryrange_m(double qval[][2]);

    //A function to calculate the pyramid number (the actual pyramid number and not the main dimension of the pyramid) and height low and height high for range search
    Pyramid::queryrange* getqueryrange(double qr[][2]);

    //A function to check whether pyramid i, intersects with qw[][]. If it intersects it return true with values of height low and height high in hlow and hhigh.
    //This function uses DetermingRange internally to calculate hlow and hhigh
    bool intersect(double qw[][2], int i,double *hlow, double *hhigh);

    //A function to height low (hlow) and height high (hhigh) in the intersection ofpyramid i and qw[][]
    void DeterminRange(double qw[][2], int i, double *hlow, double *hhigh);

    //A function to calculate absolute min of given values
    double MIN(double *r);

    //A function to calculate absolute max of given values
    double MAX(double *r);

    //A function to find approximate medians using histograms. This method calls functions of ApproximateMedian class
    void hbam(int tr, int d, double **val);

    //A function to find approximate medians using algorithm. This method calls functions of ApproximateMedian class
    void algam(int tr, int d, double **val);

    void findmedian(int tr, int d, double **val);

    bool inside(double qr[][2], int id);

    double euclideandistance(double a[], double b[]);
};



#endif	/* _PYRAMID_H */

